package com.ll.xstream;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;

import javax.xml.transform.OutputKeys;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.stream.StreamResult;

import org.xml.sax.InputSource;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.xml.StaxDriver;
/**
 * Created by daweiLiu on 2016/11/24.
 */
public class XstreamConverter {
    public static void main(String[] args) {
        XstreamConverter tester = new XstreamConverter();
        XStream xstream = new XStream(new StaxDriver());
        Teacher teacher = tester.getTeacherDetails();
        xstream.autodetectAnnotations(true);
        xstream.registerConverter(new TeacherConverter());
        //Object to XML Conversion
        String xml = xstream.toXML(teacher);
        System.out.println(formatXml(xml));
    }

    private Teacher getTeacherDetails(){
        Teacher teacher = new Teacher("Mahesh","Parashar");
        return teacher;
    }

    public static String formatXml(String xml){
        try{
            Transformer serializer= SAXTransformerFactory.newInstance().newTransformer();
            serializer.setOutputProperty(OutputKeys.INDENT, "yes");
            serializer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
            Source xmlSource=new SAXSource(new InputSource(new ByteArrayInputStream(xml.getBytes())));
            StreamResult res =  new StreamResult(new ByteArrayOutputStream());
            serializer.transform(xmlSource, res);
            return new String(((ByteArrayOutputStream)res.getOutputStream()).toByteArray());
        }catch(Exception e){
            return xml;
        }
    }
}

@XStreamAlias("teacher")
class Teacher {

    @XStreamAlias("name")
    private Name teacherName;

    public Teacher(String firstName, String lastName) {
        this.teacherName = new Name(firstName, lastName);
    }

    public Name getName(){
        return teacherName;
    }
}

class Name {
    private String firstName;
    private String lastName;

    public Name(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    public String getFirstName(){
        return firstName;
    }

    public String getLastName(){
        return lastName;
    }
}

class TeacherConverter implements Converter {

    public void marshal(Object value, HierarchicalStreamWriter writer,
                        MarshallingContext context) {
        Teacher teacher = (Teacher) value;
        writer.startNode("name");
        writer.setValue(teacher.getName().getFirstName() + "," + teacher.getName().getLastName());
        writer.endNode();
    }

    public Object unmarshal(HierarchicalStreamReader reader,
                            UnmarshallingContext context) {
        reader.moveDown();
        String[] nameparts = reader.getValue().split(",");
        Teacher teacher = new Teacher(nameparts[0],nameparts[1]);
        reader.moveUp();
        return teacher;
    }

    public boolean canConvert(Class object) {
        return object.equals(Teacher.class);
    }
}	
